package net.koodar.forge.system.menu.service;

import lombok.RequiredArgsConstructor;
import net.koodar.forge.system.menu.model.dto.ManuParamDTO;
import net.koodar.forge.system.menu.model.entity.Menu;
import net.koodar.forge.system.menu.model.vo.MenuVO;
import net.koodar.forge.system.menu.manager.MenuManager;
import net.koodar.forge.system.menu.service.assembler.MenuAssembler;
import net.koodar.forge.system.role.model.entity.RoleMenu;
import net.koodar.forge.system.menu.model.enums.MenuTypeEnum;
import net.koodar.forge.common.code.UserErrorCode;
import net.koodar.forge.common.domain.dto.MultiResponse;
import net.koodar.forge.common.domain.dto.Response;
import net.koodar.forge.common.exception.BizException;
import net.koodar.forge.common.utils.BeanUtil;
import net.koodar.forge.common.domain.model.AppUserDetails;
import net.koodar.forge.system.role.manager.RoleMenuManager;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * @author liyc
 */
@Service
@RequiredArgsConstructor
public class MenuService {

	private final MenuManager menuManager;
	private final RoleMenuManager roleMenuManager;
	private final MenuAssembler menuAssembler;

	/**
	 * 获取当前用户菜单树
	 * @return 菜单tree
	 */
	public MultiResponse<MenuVO> getMenus() {
		AppUserDetails userDetails = (AppUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		// 获取资源权限
		List<Menu> menus;
		if (userDetails.getAdministratorFlag()) {
			menus = menuManager.listMenuRoute();
		} else {
			menus = menuManager.listMenuPermissionByRoleIds(userDetails.getRoleIds());
		}

		List<MenuVO> menuVO = menuAssembler.convertToTree(null, menus);
		return MultiResponse.ok(menuVO);
	}

	public Response listTree() {
		List<Menu> menus = menuManager.list();
		List<MenuVO> menuVO = menuAssembler.convertToTree(null, menus);
		return MultiResponse.ok(menuVO);
	}

	public Response addMenu(ManuParamDTO manuParamDTO) {
		// 获取父节点id
		Long parentId = getParentId(manuParamDTO);
		manuParamDTO.setParentId(parentId);

		Menu dbMenu = menuManager.findByName(manuParamDTO.getName());
		if (dbMenu != null) {
			return Response.error(UserErrorCode.ALREADY_EXIST, String.format("当前菜单已存在[%s]", manuParamDTO.getName()));
		}

		Menu menu = menuAssembler.convertToMenu(manuParamDTO);
		menuManager.save(menu);
		return Response.ok();
	}

	public Response updateMenu(ManuParamDTO manuParamDTO) {
		Assert.notNull(manuParamDTO.getId(), "Menu id must not be null");

		// 获取父节点id
		Long parentId = getParentId(manuParamDTO);
		manuParamDTO.setParentId(parentId);

		Menu dbMenu = menuManager.findByName(manuParamDTO.getName());
		if (dbMenu != null) {
			if (!dbMenu.getId().equals(manuParamDTO.getId())) {
				return Response.error(UserErrorCode.ALREADY_EXIST, String.format("当前权限已存在[%s]", dbMenu.getName()));
			}
		}

		Menu menu = BeanUtil.copy(manuParamDTO, Menu.class);
		menuManager.save(menu);
		return Response.ok();
	}

	public Response deleteMenu(Long menuId) {
		// 校验删除的资源权限是否被绑定
		List<RoleMenu> roleMenus = roleMenuManager.findByMenuId(menuId);
		if (!roleMenus.isEmpty()) {
			throw new BizException("当前菜单权限已存在绑定的角色，请解除绑定后再试");
		}
		menuManager.removeById(menuId);
		return null;
	}

	/**
	 * 获取父节点Id
	 * @param manuParamDTO 请求参数，包含菜单类型和父节点key
	 * @return 父节点id
	 */
	private Long getParentId(ManuParamDTO manuParamDTO) {
		if (MenuTypeEnum.MENU.getValue() != manuParamDTO.getType() &&
				StringUtils.hasLength(manuParamDTO.getParentKey())) {
			Menu menu = menuManager.findByName(manuParamDTO.getParentKey());
			if (menu == null) {
				throw new BizException(String.format("数据异常 父节点[%s]不存在", manuParamDTO.getParentKey()));
			}
			return menu.getId();
		}
		return null;
	}


}
